#ifndef DIALOG_H
#define DIALOG_H

#include <stddef.h>
#include <stdlib.h>
#include <string.h>

//#include <raygui.h>

typedef struct DialogState
{
	const char *root;
	char *title;
	// textbox
	char tbxDir[512], tbxName[128]; // for textbox
	bool tbxFolderEnable, tbxFileEnable;
	// listview
	const char *listItems;
	int listScrollIdx, listActive;
	bool listUsed;
	// buttons
	bool btnUpPressed, btnRootPressed, btnOkPressed;
	bool (*work)(const char *, const char *);
} DialogState;

#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

#ifdef _WIN32
char osSlash = '\\';
#else
char osSlash = '/';
#endif // _WIN32

static const char *removeEndSlash(const char *str)
{
	int len = TextLength(str);
	if (str[len - 1] == osSlash)
		return TextSubtext(str, 0, len - 1);
	else
		return str;
}

static const char *getListItems(const char *dir)
{
	FilePathList s = LoadDirectoryFilesEx(dir, NULL, false);
	char *r[s.count];
	for (int i = 0; i < s.count; i++)
	{
		const char *ts = GetFileName(s.paths[i]);
		if (IsPathFile(ts)) // file
		{
			if (IsFileExtension(ts, ".png;.bmp;.tga;.gif;.jpg;.jpeg;.psd;.hdr;.qoi;.dds;.pkm;.ktx;.pvr;.astc"))
				ts = TextFormat("#12#%s", ts);
			else if (IsFileExtension(ts, ".wav;.mp3;.ogg;.flac;.xm;.mod;.it;.wma;.aiff"))
				ts = TextFormat("#11#%s", ts);
			else if (IsFileExtension(ts, ".txt;.info;.md;.nfo;.xml;.json;.c;.cpp;.cs;.lua;.py;.glsl;.vs;.fs"))
				ts = TextFormat("#10#%s", ts);
			else if (IsFileExtension(ts, ".exe;.bin;.raw;.msi"))
				ts = TextFormat("#200#%s", ts);
			else
				ts = TextFormat("#218#%s", ts);
		}
		else   // dir
			ts = TextFormat("#1#%s", ts);

		r[i] = malloc(TextLength(ts) * sizeof(char));
		TextCopy(r[i], ts);
	}
	UnloadDirectoryFiles(s);
	return TextJoin((const char **)r, s.count, ";");
}

static const char *getListItem(const char *listItems, int idx)
{
	int count;
	const char **items = TextSplit(listItems, ';', &count);
	return strchr(strchr(items[idx], '#') + 1, '#') + 1; // 去除#x#格式字符串
}

static void changeFolder(DialogState *state, const char *dir)
{
	TextCopy(state->tbxDir, dir);
	state->listItems = getListItems(dir);
	state->listScrollIdx = 0;
	state->listActive = -1;
}

static bool btnOkClick(DialogState *state)
{
	if (state->listUsed)
	{
		if (state->listActive >= 0)
			return state->work(state->tbxDir, getListItem(state->listItems, state->listActive));
	}
	else if (TextLength(state->tbxName) > 0)
		return state->work(state->tbxDir, state->tbxName);

	return true;
}

DialogState initDialogState(void)
{
	DialogState state = { 0 };

	state.root = removeEndSlash(GetApplicationDirectory());
	state.tbxFolderEnable = false;
	state.tbxFileEnable = false;
	state.listActive = -1;
	state.btnUpPressed = false;
	state.btnRootPressed = false;
	state.btnOkPressed = false;

	return state;
}

int GuiDialog(Rectangle *rec, DialogState *state)
{
	int r = !GuiWindowBox(*rec, TextFormat("#198#%s", state->title));

	Vector2 anchor = { 0, rec->y + 24 };

	// # 2
	anchor.y += 6 + 24 + 6;
	anchor.x = rec->x + 12;
	GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
	GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
	int bgColor = GuiGetStyle(DEFAULT, BACKGROUND_COLOR);
	GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xebebebff);
	GuiListView((Rectangle) { anchor.x, anchor.y, rec->width - 24, rec->height - 126 }, state->listItems, &state->listScrollIdx, &state->listActive);
	GuiSetStyle(DEFAULT, BACKGROUND_COLOR, bgColor);

	// # 3
	anchor.y += rec->height - 126 + 6;
	anchor.x = rec->x + 12;
	GuiLabel((Rectangle) { anchor.x, anchor.y, 28, 24 }, "Name:");
	anchor.x += 28 + 6;
	if (GuiTextBox((Rectangle) { anchor.x, anchor.y, rec->width - 58, 24 }, state->tbxName, 128, state->tbxFileEnable))
	{
		if (!state->listUsed)
		{
			state->tbxFileEnable = !state->tbxFileEnable;
			if (IsKeyPressed(KEY_ENTER) && TextLength(state->tbxDir) > 0)
				return btnOkClick(state);
		}
	}

	// # 4
	anchor.y += 24 + 6;
	anchor.x = rec->x + (rec->width - 120) / 2;
	state->btnOkPressed = GuiButton((Rectangle) { anchor.x, anchor.y, 120, 24 }, "OK");

	GuiEnableTooltip();
	// # 1
	anchor.y = rec->y + 24 + 6;
	anchor.x = rec->x + 12;
	GuiSetTooltip("Up (LCTRL+Up)");
	state->btnUpPressed = GuiButton((Rectangle) { anchor.x, anchor.y, 24, 24 }, "#117#");
	anchor.x += 24 + 6;
	GuiSetTooltip("Root Directory (LCTRL+R)");
	state->btnRootPressed = GuiButton((Rectangle) { anchor.x, anchor.y, 24, 24 }, "#181#");
	anchor.x += 24 + 6;
	GuiSetTooltip("Press SPACE to Open New Folder that Selected in List");
	GuiTextBox((Rectangle) { anchor.x, anchor.y, rec->width - 84, 24 }, state->tbxDir, 512, state->tbxFolderEnable);
	GuiDisableTooltip();

	if (state->listActive >= 0)
	{
		if (IsKeyPressed(KEY_SPACE) && TextLength(state->tbxDir) > 0)
		{
			const char *i = getListItem(state->listItems, state->listActive);
			const char *t = TextFormat("%s%c%s", state->tbxDir, osSlash, i);
			if (DirectoryExists(t)) // Dir
				changeFolder(state, t);
		}
	}

	if (IsKeyPressed(KEY_ESCAPE))
		return false;
	else if ((state->btnUpPressed || (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_UP))) && TextLength(state->tbxDir) > 0)
	{
		if (TextLength(state->tbxDir) > TextLength(state->root))
		{
			const char *t = removeEndSlash(state->tbxDir);
			if (DirectoryExists(t))
				changeFolder(state, GetPrevDirectoryPath(t));
		}
	}
	else if (state->btnRootPressed || (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_R)))
	{
		if (!TextIsEqual(state->tbxDir, state->root))
			changeFolder(state, state->root);
	}
	else if (state->btnOkPressed && TextLength(state->tbxDir) > 0)
		return btnOkClick(state);

	return r;
}

#ifdef __cplusplus
}
#endif // __cplusplus

#endif // DIALOG_H